#include "sgl_core.h"
#include <string.h>
#include "sgl.h"

static sgl_obj_t src_act_obj;

void sgl_obj_add_dirty_list(sgl_obj_t *obj)
{
    sgl_list_add_node_at_tail(&src_act_obj.dirty, &obj->dirty);
}

void sgl_obj_del_dirty_list(sgl_obj_t *obj)
{
    sgl_list_del_node(&obj->dirty);
}

sgl_list_node_t* sgl_obj_get_dirty_list_head(void)
{
    return &src_act_obj.dirty;
}

void sgl_obj_add_src_act_list(sgl_obj_t *obj)
{
    sgl_list_add_node_at_tail(&src_act_obj.node, &obj->node);
}

void sgl_obj_del_src_act_list(sgl_obj_t *obj)
{
    sgl_list_del_node(&obj->node);
}

sgl_list_node_t* sgl_obj_get_src_act_list_head(void)
{
    return &src_act_obj.node;
}

sgl_obj_t* sgl_scr_active(void)
{
    return &src_act_obj;
}

void sgl_set_scr_active_color(sgl_color_t color)
{
    int i;
    src_act_obj.style.body_color = color;
    sgl_surf_t *surf = sgl_draw_get_active_surf(sgl_scr_active());
#ifdef SGL_FULL_FRAMEBUFFER
    sgl_draw_buffer_clear(surf, color);
    sgl_draw_buffer_flush(surf, 0, 0);
#else 
    sgl_draw_set_active_surf_size(SGL_CONFIG_PANEL_XRES, SGL_CONFIG_DRAW_BUFFER_LINE);
    sgl_draw_buffer_clear(surf, color);
    for(i = 0; (i + SGL_CONFIG_DRAW_BUFFER_LINE) <= SGL_CONFIG_PANEL_YRES; i += SGL_CONFIG_DRAW_BUFFER_LINE) {
        sgl_draw_buffer_flush(surf, 0, i);
    }
    sgl_draw_set_active_surf_size(SGL_CONFIG_PANEL_XRES, SGL_CONFIG_PANEL_YRES - i);
    sgl_draw_buffer_flush(surf, 0, i);
#endif

}

sgl_color_t sgl_get_scr_active_color(void)
{
    return src_act_obj.style.body_color;
}

void sgl_obj_set_pos(sgl_obj_t *obj, int16_t x, int16_t y)
{
    obj->pos.x = obj->parent->pos.x + x;
    obj->pos.y = obj->parent->pos.y + y;
}

sgl_pos_t sgl_obj_get_pos(sgl_obj_t *obj)
{
    return obj->pos;
}

void sgl_obj_set_pos_x(sgl_obj_t *obj, int16_t x)
{
    obj->pos.x = obj->parent->pos.x + x;
}

int16_t sgl_obj_get_pos_x(sgl_obj_t *obj)
{
    return obj->pos.x;
}

void sgl_obj_set_pos_y(sgl_obj_t *obj, int16_t y)
{
    obj->pos.y = obj->parent->pos.y + y;
}

int16_t sgl_obj_get_pos_y(sgl_obj_t *obj)
{
    return obj->pos.y;
}

void sgl_obj_set_size(sgl_obj_t *obj, int16_t width, int16_t height)
{
    obj->size.w = width;
    obj->size.h = height;
}

void sgl_obj_set_size_w(sgl_obj_t *obj, int16_t width)
{
    obj->size.w = width;
}

void sgl_obj_set_size_h(sgl_obj_t *obj, int16_t height)
{
    obj->size.h = height;
}

void sgl_obj_set_style(sgl_obj_t *obj, sgl_style_t style)
{
    obj->style = style;
}

void sgl_obj_set_body_color(sgl_obj_t *obj, sgl_color_t color)
{
    obj->style.body_color = color;
}

void sgl_obj_set_text_color(sgl_obj_t *obj, sgl_color_t color)
{
    obj->style.text_color = color;
}

void sgl_obj_set_radius(sgl_obj_t *obj, int radius)
{
    obj->style.radius = radius;
}

void sgl_obj_set_parent(sgl_obj_t *obj, sgl_obj_t *parent)
{
    obj->parent = parent;
}

sgl_pos_t sgl_get_align_pos(sgl_size_t *parent_size, sgl_size_t *size, sgl_align_type_e type)
{
    sgl_pos_t ret = {.x = 0, .y = 0};
    switch(type) {                
        case SGL_ALIGN_TOP_MID:          
            ret.x = (parent_size->w - size->w)/2;
            ret.y = 0;
        break;

        case SGL_ALIGN_TOP_LEFT:
            ret.x = 2;
            ret.y = 0;
        break; 
            
        case SGL_ALIGN_TOP_RIGHT:    
            ret.x = parent_size->w - size->w - 2;
            ret.y = 0;
        break;

        case SGL_ALIGN_CENTER_MID:
            ret.x = (parent_size->w - size->w)/2;
            ret.y = (parent_size->h - size->h)/2;
        break;
        
        case SGL_ALIGN_CENTER_LEFT:
            ret.x = 2;
            ret.y = (parent_size->h - size->h)/2;
        break;

        case SGL_ALIGN_CENTER_RIGHT:
            ret.x = parent_size->w - size->w - 2;
            ret.y = (parent_size->h - size->h)/2;
        break;

        case SGL_ALIGN_BOT_LEFT:
            ret.x = 2;
            ret.y = parent_size->h - size->h;
        break;

        case SGL_ALIGN_BOT_MID:
            ret.x = (parent_size->w - size->w)/2;
            ret.y = parent_size->h - size->h;
        break;

        case SGL_ALIGN_BOT_RIGHT:
            ret.x = parent_size->w - size->w - 2;
            ret.y = parent_size->h - size->h;
        break;

        case SGL_ALIGN_TOP: 
            ret.y = 0;
        break;
        case SGL_ALIGN_CENTER: 
            ret.y = (parent_size->h - size->h)/2;
        break;
        case SGL_ALIGN_BOT: 
            ret.y = parent_size->h - size->h;
        break;
        case SGL_ALIGN_LEFT: 
            ret.x = 2;
        break;
        case SGL_ALIGN_MID: 
            ret.x = (parent_size->w - size->w)/2;
        break;
        case SGL_ALIGN_RIGHT: 
            ret.x = parent_size->w - size->w - 2; 
        break;
        default: break;
    }
    return ret;
}

void sgl_obj_set_align(sgl_obj_t *obj, sgl_align_type_e type)
{
    sgl_obj_t *parent_obj = obj->parent;
    sgl_pos_t pos = sgl_get_align_pos(&parent_obj->size, &obj->size, type);
    obj->pos.x = pos.x + parent_obj->pos.x;
    obj->pos.y = pos.y + parent_obj->pos.y;
}

void sgl_obj_set_event_cb(sgl_obj_t *obj, void (*event)(sgl_obj_t *, void *), void *data)
{
    obj->event_fn = event;
    obj->event_data = data;
}

void sgl_obj_event_cb(sgl_obj_t *obj)
{
    if(obj->event_fn) {
        obj->event_fn(obj, obj->event_data);
    }
}


void sgl_obj_set_event_status(sgl_obj_t *obj, sgl_event_type_e status)
{
    obj->ev_stat = status;
}

sgl_event_type_e sgl_obj_get_event_status(sgl_obj_t *obj)
{
    return obj->ev_stat;
}

bool sgl_obj_draw_valid(sgl_obj_t *obj)
{
    #define __BUFFER_SIZE (SGL_CONFIG_PANEL_XRES * SGL_CONFIG_DRAW_BUFFER_LINE)
    if(obj->size.w * obj->size.h > __BUFFER_SIZE)
        return false;
    else
        return true;
}

bool sgl_obj_event_active(sgl_obj_t* obj, int x, int y)
{
    if((x > (obj->pos.x + obj->size.w)) || (x < obj->pos.x) 
            || (y > (obj->pos.y + obj->size.h)) || (y < obj->pos.y)
    ) {
        return false;
    }
    else {
        return true;
    }
}

void sgl_obj_set_selected(sgl_obj_t* obj, bool status)
{
    if(status != obj->selected) {
        obj->selected = status;
        sgl_obj_add_dirty_list(obj);
    }
}

void sgl_obj_event_click(sgl_obj_t *obj)
{
    if(obj->ev_stat != SGL_EVENT_PRESSED){
        obj->ev_stat = SGL_EVENT_PRESSED;
        sgl_obj_add_dirty_list(obj);
    }
} 

void sgl_obj_event_press(sgl_obj_t *obj)
{
    if(obj->ev_stat != SGL_EVENT_PRESSED){
        obj->ev_stat = SGL_EVENT_PRESSED;
        sgl_obj_add_dirty_list(obj);
    }
}

void sgl_obj_event_release(sgl_obj_t *obj)
{
    if(obj->ev_stat != SGL_EVENT_RELEASED) {
        obj->ev_stat = SGL_EVENT_RELEASED;
        sgl_obj_add_dirty_list(obj);
    }
}

static void sgl_init_scr_act(void)
{
    sgl_obj_t* scr_act = sgl_scr_active();
    sgl_list_init(&scr_act->node);
    sgl_list_init(&scr_act->dirty);
    scr_act->parent = NULL;
    scr_act->style.text_color = SGL_WHITE;
    scr_act->style.body_color = SGL_WHITE;
    scr_act->style.radius = 0;
    scr_act->size.w = SGL_CONFIG_PANEL_XRES;
    scr_act->size.h = SGL_CONFIG_PANEL_YRES;
    scr_act->pos.x = 0;
    scr_act->pos.y = 0;
}

extern void sgl_anim_init_active_list(void);

int sgl_init(void)
{
    sgl_init_scr_act();
    sgl_anim_init_active_list();
    return 0;
}
